package cn.dm.example.aqs;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class CyclicBarrierExample3 {

    // 当线程达到指定的数值(本例即5)时,优先执行下面的代码
    private static CyclicBarrier barrier = new CyclicBarrier(5, () -> {
        log.info("callback is running");
    });

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            final int threadNum = i;
            Thread.sleep(1000);
            executor.execute(() -> {
                try {
                    race(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        executor.shutdown();
        /**
         * 结果
         * 16:41:17.724 [pool-1-thread-1] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 0 is ready
         * 16:41:18.726 [pool-1-thread-2] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 1 is ready
         * 16:41:19.741 [pool-1-thread-3] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 2 is ready
         * 16:41:20.753 [pool-1-thread-4] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 3 is ready
         * 16:41:21.767 [pool-1-thread-5] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 4 is ready
         * 16:41:21.767 [pool-1-thread-5] INFO cn.dm.example.aqs.CyclicBarrierExample3 - callback is running
         * 16:41:21.768 [pool-1-thread-5] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 4 continue
         * 16:41:21.768 [pool-1-thread-1] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 0 continue
         * 16:41:21.768 [pool-1-thread-2] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 1 continue
         * 16:41:21.768 [pool-1-thread-3] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 2 continue
         * 16:41:21.768 [pool-1-thread-4] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 3 continue
         * 16:41:22.782 [pool-1-thread-6] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 5 is ready
         * 16:41:23.796 [pool-1-thread-1] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 6 is ready
         * 16:41:24.806 [pool-1-thread-3] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 7 is ready
         * 16:41:25.822 [pool-1-thread-4] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 8 is ready
         * 16:41:26.834 [pool-1-thread-2] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 9 is ready
         * 16:41:26.834 [pool-1-thread-2] INFO cn.dm.example.aqs.CyclicBarrierExample3 - callback is running
         * 16:41:26.834 [pool-1-thread-2] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 9 continue
         * 16:41:26.834 [pool-1-thread-6] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 5 continue
         * 16:41:26.834 [pool-1-thread-1] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 6 continue
         * 16:41:26.834 [pool-1-thread-3] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 7 continue
         * 16:41:26.835 [pool-1-thread-4] INFO cn.dm.example.aqs.CyclicBarrierExample3 - 8 continue
         *
         * 由结果可知,当线程达到指定数值5时
         * 先执行log.info("callback is running"),然后再执行log.info("{} continue", threadNum);
         */
    }

    private static void race(int threadNum) throws Exception {
        Thread.sleep(1000);
        log.info("{} is ready", threadNum);
        barrier.await();
        log.info("{} continue", threadNum);
    }
}
